// Copyright (c) 2009, Michael Patraw
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * The name of Michael Patraw may not be used to endorse or promote 
//       products derived from this software without specific prior written
//       permission.
//
// THIS SOFTWARE IS PROVIDED BY Michael Patraw ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL Michael Patraw BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cctype>
#include <cstring>
#include <ctime>
#include <sstream>
#include <string>
using namespace std;

#include "game.h"
#include "MersenneTwister.h"

// Global random number generator.
MTRand mt;

enum
{
    EASY,
    MEDIUM,
    HARD,
};

void LoadCustomCharacters();

void DisplayStory();
const char * AskForString(const char * mess);
int AskForDifficulty();

int main()
{
    if (StartTui() == false)
        return 1;
    
    mt.seed((unsigned)time(NULL));
    
    LoadCustomCharacters();
	
	DisplayStory();
	
	// Ask for difficulty and name.
	const char * name = AskForString("At least you remember your Name: ");
	
	int diff = AskForDifficulty();

    if (diff == EASY) {
        Game game(new ForestWorld(GenerateForest(200, 100), name));
        game.run();
    }
    else if (diff == MEDIUM) {
        Game game(new ForestWorld(GenerateForest(400, 200), name));
        game.run();
    }
    else if (diff == HARD) {
        Game game(new ForestWorld(GenerateForest(800, 400), name));
        game.run();
    }
    
    StopTui();
    return 0;
}

void LoadCustomCharacters()
{
    // TEMP
    bool tree[at::FONT_HEIGHT][at::FONT_WIDTH] =
    {
        {0, 0, 0, 0, 0, 0},
        {0, 0, 1, 1, 0, 0},
        {0, 1, 0, 0, 1, 0},
        {1, 0, 1, 1, 0, 1},
        {0, 1, 1, 0, 1, 0},
        {1, 0, 1, 1, 0, 1},
        {0, 1, 1, 0, 1, 0},
        {0, 0, 1, 1, 0, 0},
        {0, 0, 1, 0, 0, 0},
        {0, 0, 1, 0, 0, 0},
        {0, 1, 1, 1, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
    };

    bool pinetree[at::FONT_HEIGHT][at::FONT_WIDTH] =
    {
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 1, 0, 0, 0},
        {0, 0, 1, 0, 0, 0},
        {0, 1, 0, 1, 0, 0},
        {0, 1, 0, 1, 0, 0},
        {1, 0, 1, 0, 1, 0},
        {1, 1, 0, 1, 1, 0},
        {1, 0, 1, 0, 1, 0},
        {0, 0, 1, 0, 0, 1},
        {0, 0, 1, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
    };
    
    bool boulder[at::FONT_HEIGHT][at::FONT_WIDTH] =
    {
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 1, 1, 1, 0, 0},
        {1, 0, 1, 0, 1, 0},
        {1, 0, 0, 1, 1, 1},
        {1, 0, 1, 0, 1, 0},
        {1, 0, 0, 1, 0, 1},
        {0, 1, 1, 1, 1, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
    };
    
    bool bush[at::FONT_HEIGHT][at::FONT_WIDTH] =
    {
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 1, 0, 0, 0},
        {0, 1, 0, 1, 0, 0},
        {1, 0, 1, 0, 1, 0},
        {0, 1, 0, 1, 0, 0},
        {1, 0, 1, 0, 1, 0},
        {0, 1, 1, 1, 0, 1},
        {0, 0, 1, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
    };
    
    bool stillwater[at::FONT_HEIGHT][at::FONT_WIDTH] =
    {
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 1, 0, 0, 1, 0},
        {1, 0, 1, 0, 1, 0},
        {1, 0, 0, 1, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 1, 0, 0, 1},
        {0, 1, 0, 1, 0, 1},
        {0, 1, 0, 0, 1, 0},
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0},
    };
    
    // TEMP
	at::set_font_char(0, tree);
	at::set_font_char(1, pinetree);
	at::set_font_char(2, boulder);
	at::set_font_char(3, bush);
	at::set_font_char(4, stillwater);
}

void DisplayStory()
{
    PlayWindow()->addstr(0, 0, "  You wake up from a sleep which seems to have", White);
    PlayWindow()->addstr(0, 1, "lasted forever. In a bewildered state, you try", White);
    PlayWindow()->addstr(0, 2, "to recollect the events before you were asleep.", White);
    PlayWindow()->addstr(0, 3, "  After Several hours of trying you figure", White);
    PlayWindow()->addstr(0, 4, "it's hopeless and doesn't help to improve your", White);
    PlayWindow()->addstr(0, 5, "current situation, which appears to be bad.", White);
    
    PlayWindow()->addstr(0, 7, "Press any key to continue...", Yellow);
    
    UpdateTui();
    ClearTui();

    at::getkey();
}

const char * AskForString(const char * mess)
{
    static char str[11];
    memset(str, 0, 11);
    int loc = 0;
    
    at::key key = at::ATK_NONE;
    while (key != at::ATK_RETURN && at::is_running()) {
        PlayWindow()->addstr(0, 0, mess, White);
        PlayWindow()->addstr(1, 1, str, White);
        
        UpdateTui();
        ClearTui();
        
        key = at::getkey();
        
        if (key == at::ATK_BACKSPACE && strlen(str) > 0) {
            str[loc] = 0;
            loc--;
        }
        else {
            if (isalpha((int)key) && strlen(str) < 15) {
                str[loc] = char(key);
                loc++;
            }
        }
    }
    
    return str;
}

int AskForDifficulty()
{
    int cur = 0;
    
    at::key key;
    do {
        PlayWindow()->addstr(0, 0, "How bad does this place look to you?", White);
        
        if (cur == 0)
            PlayWindow()->addstr(0, 2, "Pleasent (EASY)", Yellow);
        else
            PlayWindow()->addstr(0, 2, "Pleasent (EASY)", White);
        if (cur == 1)
            PlayWindow()->addstr(0, 3, "Not so bad (MEDIUM)", Yellow);
        else
            PlayWindow()->addstr(0, 3, "Not so bad (MEDIUM)", White);
        if (cur == 2)
            PlayWindow()->addstr(0, 4, "Bad (HARD)", Yellow);
        else
            PlayWindow()->addstr(0, 4, "Bad (HARD)", White);
        
        UpdateTui();
        ClearTui();
        
        key = at::getkey();
        
        switch (key) {
            case at::ATK_UP:
                cur--;
                if (cur < 0)
                    cur = 2;
                break;
            case at::ATK_DOWN:
                cur++;
                if (cur > 2)
                    cur = 0;
                break;
            default:
                break;
        }
        
    } while (key != at::ATK_RETURN && at::is_running());
    
    return cur;
}
